using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using Neo.MetaModel;
using Webbness.Module.VsTool.Interfaces;

namespace Webbness.Module.VsTool
{
    [Serializable]
    public class RecursiveFileCreator : BaseTemplateCreator, ISingleTemplateCreator
    {
        private List<String> _excludedDirs;
        private string[] _excludedDirsArray = new string[] {"obj", ".svn"};
        private List<String> _excludedDirsStartsWith;
        private string[] _excludedDirsStartsWithArray = new string[] {"_ReSharper", "._sgbak"};
        protected Model _model;
        protected StringDictionary _properties;

        public RecursiveFileCreator()
        {
            _excludedDirs = new List<string>(_excludedDirsArray);
            _excludedDirsStartsWith = new List<string>(_excludedDirsStartsWithArray);
        }

        #region ISingleTemplateCreator Members

        public void Run()
        {
            if (!Directory.Exists(base._outputRoot))
            {
                Directory.CreateDirectory(base._outputRoot);
            }
            CopyStaticFiles();
        }


        public ArrayList CreatedFiles
        {
            get { return base._createdFiles; }
        }

        public bool CreateFolders
        {
            get { return base._createFolders; }
            set { base._createFolders = value; }
        }

        public bool ForceOverwrite
        {
            get { return base._forceOverwrite; }
            set { base._forceOverwrite = value; }
        }

        public Model Model
        {
            get { return _model; }
            set { _model = value; }
        }

        public string OutputFolder
        {
            get { return base._outputRoot; }
            set { base._outputRoot = value; }
        }

        public string ProjectName
        {
            get { return base._projectName; }
            set { base._projectName = value; }
        }

        public StringDictionary Properties
        {
            get { return _properties; }
            set { _properties = value; }
        }

        public string Template
        {
            get { return base._template; }
            set { base._template = value; }
        }

        public string TemplatesFolder
        {
            get { return base._templatesFolder; }
            set { base._templatesFolder = value; }
        }

        #endregion

        private void CopyStaticFiles()
        {
            DirectoryInfo sourceDir = new DirectoryInfo(base._templatesFolder);
            if (!sourceDir.Exists == false)
            {
                DirectoryInfo destDir = new DirectoryInfo(base._outputRoot);
                if (destDir.Exists == false)
                {
                    destDir.Create();
                }
                CopyFilesRecursive(sourceDir, destDir);
            }
        }

        private void CopyFilesRecursive(DirectoryInfo sourceDir, DirectoryInfo destDir)
        {
            string destFileName;
            foreach (FileInfo info in sourceDir.GetFiles())
            {
                destFileName = Path.Combine(destDir.FullName, info.Name.Replace(".vtl", ""));
                if (info.Name.EndsWith(".vtl") && !String.IsNullOrEmpty(Path.GetExtension(destFileName)))
                {
                    SolutionAndProjectContext ctx = new SolutionAndProjectContext(_model);
                    ctx.Extension = Path.GetExtension(destFileName);
                    //ctx.ProjectFiles = _controllerFiles;
                    ctx.BaseDirectory = _outputRoot;
                    ctx.ProjectName = _projectName;
                    GenerateOutputFromTemplate(destFileName, info.DirectoryName, info.Name, ctx);
                    _createdFiles.Add(destFileName);
                }
                else
                {
                    destFileName = Path.Combine(destDir.FullName, info.Name);
                    if (_forceOverwrite || (File.Exists(destFileName) == false))
                    {
                        info.CopyTo(destFileName, true);
                        _createdFiles.Add(destFileName);
                    }
                }
            }
            foreach (DirectoryInfo subDir in sourceDir.GetDirectories())
            {
                DirectoryInfo newDir = new DirectoryInfo(Path.Combine(destDir.FullName, subDir.Name));
                if (String.IsNullOrEmpty(_excludedDirs.Find(delegate(String e) { return e.Equals(newDir.Name, StringComparison.InvariantCultureIgnoreCase); })) && String.IsNullOrEmpty(_excludedDirsStartsWith.Find(delegate(string e) { return newDir.Name.StartsWith(e, StringComparison.InvariantCultureIgnoreCase); })))
                {
                    if (newDir.Exists == false)
                    {
                        newDir.Create();
                    }
                    CopyFilesRecursive(subDir, newDir);
                }
            }
        }
    }
}